package fr.loof.fonzie.gigai;

import java.util.Properties;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 * @author ndeloof
 *
 */
public class InMemoryEntityManager
    implements EntityManager
{
    private EntityManager entityManager;

    public InMemoryEntityManager( String persistenceUnitName )
    {
        this( persistenceUnitName, false );
    }

    protected InMemoryEntityManager( String persistenceUnitName, boolean showSql )
    {
      Properties props = new Properties();
        props.setProperty( "javax.persistence.provider", "org.hibernate.ejb.HibernatePersistence" );
        props.setProperty( "javax.persistence.transactionType", "RESOURCE_LOCAL" );

        props.setProperty( "hibernate.dialect", "org.hibernate.dialect.HSQLDialect" );
        props.setProperty( "hibernate.hbm2ddl.auto", "create-drop" );
        props.setProperty( "showSql", String.valueOf( showSql ) );
        props.setProperty( "hibernate.connection.driver_class", "org.hsqldb.jdbcDriver" );
        props.setProperty( "hibernate.connection.username", "sa" );
        props.setProperty( "hibernate.connection.password", "" );
        props.setProperty( "hibernate.connection.url", "jdbc:hsqldb:mem:test" );
        props.setProperty( "hibernate.max_fetch_depth", "3" );

        EntityManagerFactory emf = Persistence.createEntityManagerFactory( persistenceUnitName, props );
        entityManager = emf.createEntityManager();
    }

    public void store( Object... entities )
    {
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        for ( Object entity : entities )
        {
            persist( entity );
        }
        tx.commit();
    }

    public void clear()
    {
        entityManager.clear();
    }

    public void close()
    {
        entityManager.close();
    }

    public boolean contains( Object entity )
    {
        return entityManager.contains( entity );
    }

    public Query createNamedQuery( String name )
    {
        return entityManager.createNamedQuery( name );
    }

    public Query createNativeQuery( String sqlString, Class resultClass )
    {
        return entityManager.createNativeQuery( sqlString, resultClass );
    }

    public Query createNativeQuery( String sqlString, String resultSetMapping )
    {
        return entityManager.createNativeQuery( sqlString, resultSetMapping );
    }

    public Query createNativeQuery( String sqlString )
    {
        return entityManager.createNativeQuery( sqlString );
    }

    public Query createQuery( String qlString )
    {
        return entityManager.createQuery( qlString );
    }

    public <T> T find( Class<T> entityClass, Object primaryKey )
    {
        return entityManager.find( entityClass, primaryKey );
    }

    public void flush()
    {
        entityManager.flush();
    }

    public Object getDelegate()
    {
        return entityManager.getDelegate();
    }

    public FlushModeType getFlushMode()
    {
        return entityManager.getFlushMode();
    }

    public <T> T getReference( Class<T> entityClass, Object primaryKey )
    {
        return entityManager.getReference( entityClass, primaryKey );
    }

    public EntityTransaction getTransaction()
    {
        return entityManager.getTransaction();
    }

    public boolean isOpen()
    {
        return entityManager.isOpen();
    }

    public void joinTransaction()
    {
        entityManager.joinTransaction();
    }

    public void lock( Object entity, LockModeType lockMode )
    {
        entityManager.lock( entity, lockMode );
    }

    public <T> T merge( T entity )
    {
        return entityManager.merge( entity );
    }

    public void persist( Object entity )
    {
        entityManager.persist( entity );
    }

    public void refresh( Object entity )
    {
        entityManager.refresh( entity );
    }

    public void remove( Object entity )
    {
        entityManager.remove( entity );
    }

    public void setFlushMode( FlushModeType flushMode )
    {
        entityManager.setFlushMode( flushMode );
    }
}
